package com.anttribe.dbdocument.config;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import lombok.Getter;

/**
 * @author zhaoyong
 * @date 2021/10/6 0006
 */
@Getter
public class DBDataProcessorConfiguration {

    /**
     * 默认配置
     */
    private static final DBDataProcessorConfiguration DEFAULT_DB_DATAPROCESSOR_CONFIGURATION =
        DBDataProcessorConfiguration.builder().build();

    // 过滤表优先级: 指定(表名 > 表前缀 > 表后缀) > 排除(表名 > 表前缀 > 表后缀)
    /**
     * 指定表名
     */
    private List<String> designatedTableNames;

    /**
     * 指定表前缀
     */
    private List<String> designatedTablePrefixs;

    /**
     * 指定表后缀
     */
    private List<String> designatedTableSuffixs;

    /**
     * 排除的表名
     */
    private List<String> excludeTableNames;

    /**
     * 排除的表名的前缀
     */
    private List<String> excludeTablePrefixs;

    /**
     * 排除的表名的后缀
     */
    private List<String> excludeTableSuffixs;

    /**
     * 默认构造器
     */
    private DBDataProcessorConfiguration() {}

    /**
     * 获取builder对象
     *
     * @return
     */
    public static DBDataProcessorConfigurationBuilder builder() {
        return new DBDataProcessorConfigurationBuilder();
    }

    /**
     * @author zhaoyong
     * @date 2021/10/6 0006
     */
    public static class DBDataProcessorConfigurationBuilder {

        /**
         * 默认表名正则
         */
        private static final String TABLE_NAME_PATTERN_REG = "(^_([a-zA-Z0-9]_?)+$)|(^[a-zA-Z](_?[a-zA-Z0-9])*_?$)";

        /**
         * 校验表名正则
         */
        private static final Pattern VERIFY_TABLE_NAME_PATTERN =
            Pattern.compile(TABLE_NAME_PATTERN_REG, Pattern.CASE_INSENSITIVE);

        /**
         * 校验表前缀正则
         */
        private static final String VERIFY_TABLE_PREFIX_PATTERN_REG =
            "(^_([a-zA-Z0-9]_?)+)|(^[a-zA-Z](_?[a-zA-Z0-9])*_?)";

        /**
         * 校验表前缀正则
         */
        private static final Pattern VERIFY_TABLE_PREFIX_PATTERN =
            Pattern.compile(VERIFY_TABLE_PREFIX_PATTERN_REG, Pattern.CASE_INSENSITIVE);

        /**
         * 校验表后缀正则
         */
        private static final String VERIFY_TABLE_SUFFIX_PATTERN_REG =
            "(_([a-zA-Z0-9]_?)+$)|([a-zA-Z](_?[a-zA-Z0-9])*_?$)";

        /**
         * 校验表后缀正则
         */
        private static final Pattern VERIFY_TABLE_SUFFIX_PATTERN =
            Pattern.compile(VERIFY_TABLE_SUFFIX_PATTERN_REG, Pattern.CASE_INSENSITIVE);

        // 过滤表优先级: 指定(表名 > 表前缀 > 表后缀) > 排除(表名 > 表前缀 > 表后缀)
        /**
         * 指定表名
         */
        private List<String> designatedTableNames;

        /**
         * 指定表前缀
         */
        private List<String> designatedTablePrefixs;

        /**
         * 指定表后缀
         */
        private List<String> designatedTableSuffixs;

        /**
         * 排除的表名
         */
        private List<String> excludeTableNames;

        /**
         * 排除的表名的前缀
         */
        private List<String> excludeTablePrefixs;

        /**
         * 排除的表名的后缀
         */
        private List<String> excludeTableSuffixs;

        /**
         * 指定的数据库表名
         *
         * @param designatedTableNames
         * @return DBDataProcessorConfigurationBuilder
         */
        public DBDataProcessorConfigurationBuilder designatedTableNames(String... designatedTableNames) {
            if (!ArrayUtils.isEmpty(designatedTableNames)) {
                this.designatedTableNames = Arrays.stream(designatedTableNames).filter(designatedTableName -> {
                    if (StringUtils.isBlank(designatedTableName)) {
                        return false;
                    }
                    Matcher m = VERIFY_TABLE_NAME_PATTERN.matcher(designatedTableName);
                    return m.matches();
                }).collect(Collectors.toList());
            }

            return this;
        }

        /**
         * 指定的数据库表前缀
         *
         * @param designatedTablePrefixs
         * @return DBDataProcessorConfigurationBuilder
         */
        public DBDataProcessorConfigurationBuilder designatedTablePrefixs(String... designatedTablePrefixs) {
            if (!ArrayUtils.isEmpty(designatedTablePrefixs)) {
                this.designatedTablePrefixs = Arrays.stream(designatedTablePrefixs).filter(designatedTablePrefix -> {
                    if (StringUtils.isBlank(designatedTablePrefix)) {
                        return false;
                    }
                    Matcher m = VERIFY_TABLE_PREFIX_PATTERN.matcher(designatedTablePrefix);
                    return m.matches();
                }).collect(Collectors.toList());
            }

            return this;
        }

        /**
         * 指定的数据库表后缀
         *
         * @param designatedTableSuffixs
         * @return DBDataProcessorConfigurationBuilder
         */
        public DBDataProcessorConfigurationBuilder designatedTableSuffixs(String... designatedTableSuffixs) {
            if (!ArrayUtils.isEmpty(designatedTableSuffixs)) {
                this.designatedTableSuffixs = Arrays.stream(designatedTableSuffixs).filter(designatedTableSuffix -> {
                    if (StringUtils.isBlank(designatedTableSuffix)) {
                        return false;
                    }
                    Matcher m = VERIFY_TABLE_SUFFIX_PATTERN.matcher(designatedTableSuffix);
                    return m.matches();
                }).collect(Collectors.toList());
            }

            return this;
        }

        /**
         * 排除的数据库表名
         *
         * @param excludeTableNames
         * @return DBDataProcessorConfigurationBuilder
         */
        public DBDataProcessorConfigurationBuilder excludeTableNames(String... excludeTableNames) {
            if (!ArrayUtils.isEmpty(excludeTableNames)) {
                this.excludeTableNames = Arrays.stream(excludeTableNames).filter(excludeTableName -> {
                    if (StringUtils.isBlank(excludeTableName)) {
                        return false;
                    }
                    Matcher m = VERIFY_TABLE_NAME_PATTERN.matcher(excludeTableName);
                    return m.matches();
                }).collect(Collectors.toList());
            }

            return this;
        }

        /**
         * 排除的数据库表前缀
         *
         * @param excludeTablePrefixs
         * @return DBDataProcessorConfigurationBuilder
         */
        public DBDataProcessorConfigurationBuilder excludeTablePrefixs(String... excludeTablePrefixs) {
            if (!ArrayUtils.isEmpty(excludeTablePrefixs)) {
                this.excludeTablePrefixs = Arrays.stream(excludeTablePrefixs).filter(excludeTablePrefix -> {
                    if (StringUtils.isBlank(excludeTablePrefix)) {
                        return false;
                    }
                    Matcher m = VERIFY_TABLE_PREFIX_PATTERN.matcher(excludeTablePrefix);
                    return m.matches();
                }).collect(Collectors.toList());
            }
            return this;
        }

        /**
         * 排除的表后缀列表
         *
         * @param excludeTableSuffixs
         * @return DBDataProcessorConfigurationBuilder
         */
        public DBDataProcessorConfigurationBuilder excludeTableSuffixs(String... excludeTableSuffixs) {
            if (!ArrayUtils.isEmpty(excludeTableSuffixs)) {
                this.excludeTableSuffixs = Arrays.stream(excludeTableSuffixs).filter(excludeTableSuffix -> {
                    if (StringUtils.isBlank(excludeTableSuffix)) {
                        return false;
                    }
                    Matcher m = VERIFY_TABLE_SUFFIX_PATTERN.matcher(excludeTableSuffix);
                    return m.matches();
                }).collect(Collectors.toList());
            }
            return this;
        }

        /**
         * 构造DBDataProcessorConfiguration对象
         *
         * @return DBDataProcessorConfiguration
         */
        public DBDataProcessorConfiguration build() {
            DBDataProcessorConfiguration configuration = new DBDataProcessorConfiguration();
            configuration.designatedTableNames = this.designatedTableNames;
            configuration.designatedTablePrefixs = this.designatedTablePrefixs;
            configuration.designatedTableSuffixs = this.designatedTableSuffixs;
            configuration.excludeTableNames = this.excludeTableNames;
            configuration.excludeTablePrefixs = this.excludeTablePrefixs;
            configuration.excludeTableSuffixs = this.excludeTableSuffixs;
            return configuration;
        }
    }
}
